package com.nuyoah.controller;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nuyoah.common.lang.Const;
import com.nuyoah.common.lang.Result;
import com.nuyoah.entity.Role;
import com.nuyoah.entity.RoleMenu;
import com.nuyoah.entity.UserRole;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 角色相关接口
 *
 * @author xiaoming
 * @since 2024-03-26
 */
@RestController
@RequestMapping("/sys/role")
public class RoleController extends BaseController{

    /**
     * 根据角色ID获取角色信息及其菜单权限。
     *
     * @param id 角色ID
     * @return 返回角色信息及其菜单ID列表
     */
    @GetMapping("/info/{id}")
    @PreAuthorize("hasAuthority('sys:role:list')")
    public Result info(@PathVariable("id") Long id) {

        // 从角色服务中获取角色信息
        Role role = roleService.getById(id);

        // 获取角色对应的菜单权限
        List<RoleMenu> roleMenus = roleMenuService.list(new QueryWrapper<RoleMenu>().eq("role_id", id));
        List<Long> menuIds = roleMenus.stream().map(p -> p.getMenuId()).collect(Collectors.toList());

        // 设置角色菜单ID列表
        role.setMenuIds(menuIds);
        return Result.succ(role);
    }

    /**
     * 分页查询角色列表。
     *
     * @param name 角色名称（可选）
     * @return 返回角色分页列表
     */
    @PreAuthorize("hasAuthority('sys:role:list')")
    @GetMapping("/list")
    public Result list(String name) {

        // 根据角色名称进行分页查询
        Page<Role> pageData = roleService.page(getPage(),
                new QueryWrapper<Role>()
                        .like(StrUtil.isNotBlank(name), "name", name)
        );

        return Result.succ(pageData);
    }

    /**
     * 保存角色信息。
     *
     * @param role 角色信息
     * @return 返回保存后的角色信息
     */
    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:role:save')")
    public Result save(@Validated @RequestBody Role role) {

        // 设置创建时间及状态
        role.setCreated(LocalDateTime.now());
        role.setStatus(Const.STATUS_ON);

        // 保存角色信息
        roleService.save(role);
        return Result.succ(role);
    }

    /**
     * 更新角色信息。
     *
     * @param role 角色信息
     * @return 返回更新后的角色信息
     */
    @PutMapping("/update")
    @PreAuthorize("hasAuthority('sys:role:update')")
    public Result update(@Validated @RequestBody Role role) {

        // 设置更新时间
        role.setUpdated(LocalDateTime.now());

        // 更新角色信息
        roleService.updateById(role);

        // 清除关联用户的角色信息缓存
        userService.clearUserAuthorityInfoByRoleId(role.getId());

        return Result.succ(role);
    }

    /**
     * 批量删除角色及其关联的菜单和用户角色关系。
     *
     * @param ids 角色ID数组
     * @return 返回删除成功的提示信息
     */
    @DeleteMapping("/delete")
    @PreAuthorize("hasAuthority('sys:role:delete')")
    @Transactional
    public Result info(@RequestBody Long[] ids) {

        // 批量删除角色
        roleService.removeByIds(Arrays.asList(ids));

        // 删除角色对应的菜单关系和用户角色关系
        userRoleService.remove(new QueryWrapper<UserRole>().in("role_id", ids));
        roleMenuService.remove(new QueryWrapper<RoleMenu>().in("role_id", ids));

        // 更新缓存，清除关联角色的用户权限信息
        Arrays.stream(ids).forEach(id -> {
            userService.clearUserAuthorityInfoByRoleId(id);
        });

        return Result.succ("");
    }

    /**
     * 给角色授予菜单权限。
     *
     * @param roleId 角色ID
     * @param menuIds 菜单ID数组
     * @return 返回授予成功的菜单ID列表
     */
    @Transactional
    @PostMapping("/perm/{roleId}")
    @PreAuthorize("hasAuthority('sys:role:perm')")
    public Result info(@PathVariable("roleId") Long roleId, @RequestBody Long[] menuIds) {

        // 准备角色菜单关系列表
        List<RoleMenu> sysRoleMenus = new ArrayList<>();
        Arrays.stream(menuIds).forEach(menuId -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setMenuId(menuId);
            roleMenu.setRoleId(roleId);

            sysRoleMenus.add(roleMenu);
        });

        // 先清除旧的角色菜单关系，再保存新的关系
        roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("role_id", roleId));
        roleMenuService.saveBatch(sysRoleMenus);

        // 清除角色的用户权限信息缓存
        userService.clearUserAuthorityInfoByRoleId(roleId);

        return Result.succ(menuIds);
    }



}
